/*
 *  +----------------------------------------------------------------------
 *  | sophon [ A FAST GAME FRAMEWORK ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2023-2029 All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed ( http:www.apache.org/licenses/LICENSE-2.0 )
 *  +----------------------------------------------------------------------
 *  | Author: jqiris <1920624985@qq.com>
 *  +----------------------------------------------------------------------
 */

use std::fs::File;
use std::future::Future;
use std::io::Read;
use std::panic;
use std::sync::Once;

use anyhow::Result;
use tokio::runtime::Runtime;

pub use byte::*;
pub use counter::*;

use crate::{discover::*, error, logger::*, report, treaty::*};

mod byte;
mod counter;

static INIT: Once = Once::new();

//获取环境变量信息
pub fn get_env_default(key: &str, def_val: String) -> String {
    match std::env::var(key) {
        Ok(val) => val,
        Err(_) => def_val,
    }
}

//打开文件并读取所有内容
pub fn read_all(path: String) -> Result<String> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}

//异常捕获安全运行
pub fn safe_run(f: fn()) {
    INIT.call_once(|| {
        panic::set_hook(Box::new(|info| {
            report!("panic {}", info);
        }));
    });
    let _ = panic::catch_unwind(|| {
        f();
    });
}

pub fn join_path(prefix: String, suffix: String) -> String {
    if suffix.len() < 1 {
        return prefix.to_string();
    }
    format!("{}/{}", prefix, suffix)
}

//系统维护
pub fn server_maintain(
    req_maintain: &ServerMaintainReq,
    maintained: bool,
    mut srv: Server,
) -> bool {
    if srv.server_id != req_maintain.server_id {
        error!(
            "maintain server not current server,current:{},req:{}",
            srv.server_id, req_maintain.server_id
        );
        return false;
    }
    let mut resp = true;
    if req_maintain.req_state == 1 && !maintained {
        srv.maintained = Some(true);
        srv.silent = Some(0);
        block_on(async {
            match register(&srv).await {
                Ok(_) => {
                    report!("服务器:{},进入维护状态", srv.server_id);
                }
                Err(err) => {
                    error!("maintain true register err:{}", err);
                    resp = false;
                }
            }
        });
    } else if req_maintain.req_state == 2 && maintained {
        srv.maintained = Some(false);
        srv.silent = Some(0);
        block_on(async {
            match register(&srv).await {
                Ok(_) => {
                    report!("服务器:{},解除维护状态", srv.server_id);
                }
                Err(err) => {
                    error!("maintain false register err:{}", err);
                    resp = false;
                }
            }
        });
    }
    return resp;
}

//md5加密
pub fn md5(s: String) -> String {
    format!("{:x}", md5::compute(s.as_bytes()))
}

//i64 to u64
pub fn i64_to_u64(x: i64) -> u64 {
    let mut bytes = x.to_ne_bytes();
    if x < 0 {
        bytes.iter_mut().for_each(|b| *b = !*b);
    }
    u64::from_ne_bytes(bytes)
}

//block on
pub fn block_on<F: Future>(future: F) -> F::Output {
    Runtime::new().unwrap().block_on(future)
}
